#include "state.h"
#include "graphics.h"
#include "thread.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#include <GL/glxext.h>

int bind_sprite(sprite_t *spr, char *data){
    if(spr == NULL || data == NULL){return 0;}
    glGenTextures(1, &(spr->tex.texture));
    glBindTexture(GL_TEXTURE_2D, spr->tex.texture);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    // when texture area is small, bilinear filter the closest mipmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                             GL_LINEAR_MIPMAP_NEAREST);
    // when texture area is large, bilinear filter the original
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // the texture wraps over at the edges (repeat)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, spr->loc.w, spr->loc.h,
                               GL_RGBA, GL_UNSIGNED_BYTE, data);
    return 1;
}

//Something that is very important to understand about OpenGL and blending:
//http://www.opengl.org/resources/faq/technical/transparency.htm
//In other words always draw your object back to front!

void render_gui(){
    int i;
    sprite_list_node_t** sprite_lists;
    sprite_list_node_t* sprite_node;
    sprite_t *spr;

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glLoadIdentity();                           // Reset The Current Matrix
    float width = 800.0f;
    float height = 600.0f;
    //glMatrixMode(GL_MODELVIEW);
    glMatrixMode(GL_PROJECTION);
    glOrtho(0.0f, width, 0.0f, height, -7.0f, 8.0f);
    //glFrustum(0.0f, 800.0f, 0.0f, 600.0f, -10.0f, 10.0f);
    //glViewport(0, 0, 800, 600);
    //gluPerspective(45.0f, 1.0f * 800.0 / 600.0, 1.0f, 100.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);     // Turn Blending On
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_DEPTH_TEST);

    sprite_lists = get_sprite_lists();
    for(i = 0; i < get_num_sprite_lists; i++){
        for(sprite_node = sprite_lists[i]; 
                sprite_node && sprite_node->spr > 0; 
                sprite_node = sprite_node->next){
            //printf("%ld, %ld\n", sprite_node->prev, sprite_node->next);
            spr = sprite_node->spr;
            glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D, sprite_node->spr->tex.texture);
            glBegin(GL_QUADS);
            glTexCoord2f(spr->tex.texx, spr->tex.texy); glVertex3s(spr->loc.x,spr->loc.y,1.0);
            glTexCoord2f(spr->tex.texx2, spr->tex.texy); glVertex3s(spr->loc.x+spr->loc.w,spr->loc.y,1.0);
            glTexCoord2f(spr->tex.texx2, spr->tex.texy2); glVertex3s(spr->loc.x+spr->loc.w,spr->loc.y+spr->loc.h,1.0);
            glTexCoord2f(spr->tex.texx, spr->tex.texy2); glVertex3s(spr->loc.x,spr->loc.y+spr->loc.h,1.0);
            glEnd();
        }
    }

    int g_bDoubleBuffered = 1;//FIXME
    if(g_bDoubleBuffered){
        glXSwapBuffers(display, window); // Buffer swap does implicit glFlush
    }else{
        glFlush(); // Explicit flush for single buffered case 
    }
}

void init_opengl(){
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glEnable(GL_TEXTURE_2D);
}

